﻿using BLL;
using NUnrar.Archive;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace GUI.UserInterfaces
{
    public partial class GUIDemosDownload : Form
    {
        private static GUIDemosDownload form = null;
        private Queue<string> demoList = new Queue<string>();

        public GUIDemosDownload(List<Record> list)
        {
            InitializeComponent();

            foreach (var demo in list)
            {
                demoList.Enqueue(demo.File);
                listBoxDemo.Items.Add(demo.File);
            }

            DownloadFile();
        }

        private void DownloadFile()
        {
            if (demoList.Any())
            {
                if (!System.IO.Directory.Exists(UTIL.KZSettings.DemoFolder))
                {
                    System.IO.Directory.CreateDirectory(UTIL.KZSettings.DemoFolder);
                }

                var demo = demoList.Dequeue();
                var folder = Path.Combine(UTIL.KZSettings.DemoFolder, demo);

                listBoxDemo.Items.Remove(demo);

                if (!System.IO.File.Exists(folder))
                {
                    WebClient client = new WebClient();

                    client.DownloadProgressChanged += client_DownloadProgressChanged;
                    client.DownloadFileCompleted += client_DownloadFileCompleted(folder);

                    var link = new Uri(Path.Combine(UTIL.KZSettings.DemoURL, demo));

                    client.DownloadFileAsync(link, folder);

                    lblDemo.Text = demo;
                }
                else
                {
                    DownloadFile();
                }

                return;
            }
            else
            {
                MessageBox.Show("All demos have been downloaded :-)", "Demo download", MessageBoxButtons.OK, MessageBoxIcon.Information);

                CloseForm();
            }
        }

        private AsyncCompletedEventHandler client_DownloadFileCompleted(string filename)
        {
            Action<object, AsyncCompletedEventArgs> action = (sender, e) =>
            {
                var _filename = filename;

                if (e.Error != null)
                {
                    throw e.Error;
                }
                else
                {
                    try
                    {
                        RarArchive archive = RarArchive.Open(_filename);

                        foreach (RarArchiveEntry entry in archive.Entries)
                        {
                            // Normally we would use entry.FilePath() 
                            // but some of the archives have wrong headers
                            // and cause the Exception throw of IllegalArguments
                            // therefore this is a sloppy, but a secure way to do this

                            string path = _filename.Remove(_filename.Length - 4) + ".dem";

                            entry.WriteToFile(path);
                        }
                    }
                    catch(NUnrar.InvalidRarFormatException)
                    {
                        MessageBox.Show("The rar archive is broken, please contact an administrator", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                }

                DownloadFile();
            };

            return new AsyncCompletedEventHandler(action);
        }

        void client_DownloadProgressChanged(object sender, System.Net.DownloadProgressChangedEventArgs e)
        {
            double bytesIn = double.Parse(e.BytesReceived.ToString());
            double totalBytes = double.Parse(e.TotalBytesToReceive.ToString());
            double percentage = bytesIn / totalBytes * 100;

            progressBar1.Value = int.Parse(Math.Truncate(percentage).ToString());
        }

        public static void ShowForm(List<Record> list)
        {
            if (form != null)
            {
                form.BringToFront();
            }
            else
            {
                form = new GUIDemosDownload(list);
                form.Show();
            }
        }

        public void CloseForm()
        {
            if (form != null)
            {
                form.Close();
                demoList.Clear();
                GUIDemosDownload_FormClosed(null, null);
            }
        }

        private void GUIDemosDownload_FormClosed(object sender, System.Windows.Forms.FormClosedEventArgs e)
        {
            form = null;
            demoList.Clear();
        }
    }
}
